home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / AdobeExamples / NX_Scroll / EpsfParser.m < prev    next >
Text File  |  1992-12-19  |  6KB  |  295 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34.  *    EpsfParser.m
  35.  *
  36.  *    This class reads in a distilled epsf file and attempts to parse through the file
  37.  *    and insert the paths into the programs data structures.
  38.  *
  39.  *    Version:    2.0
  40.  *    Author:    Ken Fromm
  41.  *    History:
  42.  *            03-07-91        Added this comment.
  43.  */
  44.  
  45. #import "EpsfParser.h"
  46. #import "ScrollApp.h"
  47. #import "iparser.h"
  48.  
  49. #import <appkit/Panel.h>
  50. #import <appkit/nextstd.h>
  51. #import <stdio.h>
  52.  
  53. static char  *processToLineEnd();
  54. static char  *processToField();
  55.  
  56. static BOOL checkForPS(char **dataptr, float *level_dsc, float *level_epsf)
  57. {
  58.     char     *dp;
  59.     
  60.     BOOL    invalid_ps = YES;
  61.  
  62.     *level_dsc = *level_epsf = 0.0;
  63.  
  64.     dp = *dataptr;
  65.     if (!strncmp(dp, "%!PS-Adobe-", 11))
  66.     {
  67.         invalid_ps = NO;
  68.  
  69.         dp +=11;
  70.         sscanf(dp, "%f", level_dsc);
  71.  
  72.         while(*dp == ' ') dp++;
  73.         if (!strncmp(dp, "EPSF-", 5))
  74.         {
  75.             dp += 5;
  76.             sscanf(dp, "%f", level_dsc);
  77.         }
  78.     }
  79.     
  80.     *dataptr = processToLineEnd(dp);
  81.  
  82.     return invalid_ps;
  83. }
  84.  
  85. static int checkType(char *s0, char *s1, char *s2, char *s3)
  86. {
  87.     int    type = PS_NOTYPE;
  88.     
  89.     if (s0 && *s0 && s1 && *s1)
  90.     {
  91.         if (!strncmp(s0, "Adobe", 5) && !strncmp(s1, "Illustrator", 11))
  92.             type = PS_ILLUSTRATOR;
  93.         else if (!strncmp(s0, "Glenn", 5) &&
  94.                 !strncmp(s1, "Reid", 4) &&
  95.                 !strncmp(s3, "still.ps", 8))
  96.             type = PS_DISTILLERY;
  97.     }
  98.  
  99.     return type;
  100. }
  101.  
  102. static BOOL validateCreator(int ps_creator)
  103. {
  104.     if (ps_creator == PS_DISTILLERY)
  105.         return YES;
  106.     else
  107.         return NO;
  108. }
  109.  
  110. static void convertBounds(float *aBox, NXRect *aRect)
  111. {
  112.     aRect->origin.x = aBox[0];
  113.     aRect->origin.y = aBox[1];
  114.     aRect->size.width = aBox[2] - aBox[0];
  115.     aRect->size.height = aBox[3] - aBox[1];
  116. }
  117.             
  118. static char *processToLineEnd(char *dp)
  119. {
  120.     dp = strchr(dp,'\n'); dp++;
  121.     
  122.     return dp;
  123. }
  124.  
  125. static char *processToField(char *dp)
  126. {
  127.  
  128.     dp = strchr(dp,':'); dp++;
  129.     if (*dp == ' ')
  130.     {
  131.         strrchr(dp, ' ');
  132.         dp++;
  133.     }
  134.     
  135.     return dp;
  136. }
  137.  
  138. static void  checkHeader(char **dataptr, float *bbox, BOOL *validBBox, int  *creator)
  139. {
  140.     BOOL    done = NO;
  141.  
  142.     char        *dp;
  143.     
  144.     char        str0[40], str1[40], str2[40], str3[40];
  145.  
  146.     int        matches = 0;
  147.  
  148.     *creator = PS_NOTYPE;
  149.     *validBBox = NO;
  150.  
  151.     dp = *dataptr;
  152.     while (*dp && !done)
  153.     {
  154.         if (strncmp(dp, "%%", 2) == 0)
  155.         {
  156.             dp += 2;
  157.             if (strncmp(dp, "EndComments", 11) == 0)
  158.                 done = YES;
  159.             else if (strncmp(dp, "Creator:", 8) == 0)
  160.             {
  161.                 dp = processToField(dp);
  162.                 sscanf(dp, "%s%s%s%s", str0, str1, str2, str3);
  163.                 *creator = checkType(str0, str1, str2, str3);
  164.             }
  165.             else if (strncmp(dp, "BoundingBox:", 12) == 0)
  166.             {
  167.                 dp = processToField(dp);
  168.                 if (strncmp(dp, "(atend)", 7) != 0)
  169.                 {
  170.                     matches = sscanf(dp, "%f %f %f %f",
  171.                         &bbox[0], &bbox[1], &bbox[2], &bbox[3]);
  172.                     if ((matches && matches != 4) ||
  173.                          (matches == 4 &&
  174.                         (bbox[2] == bbox[0] || bbox[3] == bbox[1])))
  175.                         *validBBox = YES;
  176.                 }
  177.             }
  178.         }    
  179.         dp = processToLineEnd(dp);
  180.     }
  181.  
  182.     *dataptr = dp;
  183.     return;
  184. }
  185.  
  186. static void  checkTrailer(char **dataptr, float *bbox, BOOL *validBBox)
  187. {
  188.     BOOL    done = NO;
  189.  
  190.     char        *dp;
  191.     
  192.     int        matches = 0;
  193.  
  194.     *validBBox = NO;
  195.  
  196.     dp = *dataptr;
  197.     while (*dp && !done)
  198.     {
  199.         if (strncmp(dp, "%%", 2) == 0)
  200.         {
  201.             dp += 2;
  202.             if (strncmp(dp, "BoundingBox:", 12) == 0)
  203.             {
  204.                 dp = processToField(dp);
  205.                 matches = sscanf(dp, "%f %f %f %f",
  206.                         &bbox[0], &bbox[1], &bbox[2], &bbox[3]);
  207.                 if (matches == 4 && bbox[2] != bbox[0] && bbox[3] != bbox[1])
  208.                  {
  209.                      done = YES;
  210.                     *validBBox = YES;
  211.                 }
  212.             }
  213.         }
  214.         dp = processToLineEnd(dp);
  215.     }
  216.  
  217.     *dataptr = dp;
  218.     return;
  219. }
  220.  
  221. @implementation EpsfParser
  222.  
  223. /*
  224.  * Checks for valid PS file, gets the bounding box and checks for
  225.  * the creator. The creator will let us determine whether we can read
  226.  * the file into our own graphics structure.
  227.  */
  228. - readPSFromStream:(NXStream *)stream
  229. {
  230.     id        graphic;
  231.  
  232.     BOOL    error = YES, validBBox = NO;
  233.  
  234.     char     *data;
  235.     
  236.     float        bbox[4];
  237.  
  238.     int         length,        /* the number of bytes in data */
  239.             maxlen;        /* size of vm_allocated region */
  240.  
  241.     bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0;
  242.  
  243.     NXGetMemoryBuffer(stream, &data, &length, &maxlen);
  244.     if (length)
  245.     {
  246.         error = checkForPS(&data, &level_dsc, &level_epsf);
  247.         if (!error)
  248.         {
  249.             error = YES;
  250.             checkHeader(&data, bbox, &validBBox, &creator);
  251.             if (validateCreator(creator))
  252.             {
  253.                 if (!iparse(&data))
  254.                 {
  255.                     if (!validBBox)
  256.                         checkTrailer(&data, bbox, &validBBox);
  257.                     
  258.                     if (validBBox)
  259.                     {
  260.                         convertBounds(bbox, &bounds);
  261.                         error = NO;
  262.                     }
  263.                     else
  264.                         NXRunAlertPanel("Load File",
  265.                         "Invalid bounding box. Cannot open.", 
  266.                         "OK", NULL, NULL);
  267.                 }
  268.             }
  269.             else
  270.                 NXRunAlertPanel("Load File",
  271.                     "Not a distilled file. Cannot open.", 
  272.                     "OK", NULL, NULL);
  273.         }
  274.         else
  275.             NXRunAlertPanel("Load File", "Not a valid PS file. Cannot open.", 
  276.                     "OK", NULL, NULL);    
  277.     }
  278.     else
  279.         NXRunAlertPanel("Load File", "Invalid file. Cannot open.", 
  280.                 "OK", NULL, NULL);    
  281.  
  282.     if (error)
  283.         return nil;
  284.     else
  285.         return self;
  286. }
  287.  
  288. - getBounds:(NXRect *) aRect
  289. {
  290.     *aRect = bounds;
  291. }
  292.  
  293. @end
  294.  
  295.